/*
 * AtInstruction.java
 * 
 * last update: 15.01.2010 by Stefan Saru
 * 
 * author:	Alec(panovici@elcom.pub.ro)
 *
 * Obs:  
 */

package engine;

import java.util.*;

/**
 * Implements the @(... OR ... ) instruction
 * !! this executes ONLY ONE TIME PER Clock2 ! because it attaches to all 
 *  monitors, and then detaches from all, all the values are updated, 
 *  even if they were not producing the trigger. So, if they change in 
 *  the same Clock2, nothing happens anymore.
 */
class AtInstruction extends DefaultInstruction{
  Vector theEvents;
  Object semaphore;
  
  AtInstruction(NameSpace ns, int delayBefore,
                InstructionDescription desc, DefaultInstruction block){
    super(ns, delayBefore, desc);
    add(block);
    theEvents = new Vector();
    semaphore = new Object();
  }

  public void execute()
    throws InterpretTimeException, SimulationStoppedException
  {
    xConsole.trace(toString());
    waitToRun();
    synchronized(semaphore) {
      while (!alreadyOn()) {
        xConsole.debug("waiting...");
        try {
          ControlThread.goSleepy(semaphore);
        } catch (InterruptedException intex) {
          if (intex instanceof SimulationStoppedException)
            throw (SimulationStoppedException) intex;
        }
        xConsole.debug("woken up...");
      }
      consume();
      xConsole.trace(toString() + "CONTINUE \\/");
    }
  }
  
  //checks monitors to see wether anyone is triggered
  boolean nothingHappen(){
    for(Enumeration e = theEvents.elements() ; e.hasMoreElements() ; )
      if(((ValueChangeMonitor)e.nextElement()).isTriggd())return false;
    return true;
  }

  void consume() {
    for(Enumeration e = theEvents.elements() ; e.hasMoreElements() ; ){
      ValueChangeMonitor vcm = (ValueChangeMonitor)e.nextElement();
      synchronized(vcm){  //prevent desynch. between Monitor.trigger & attach
        vcm.consume();
      }
    }
  }

  boolean alreadyOn(){
    for(Enumeration e = theEvents.elements() ; e.hasMoreElements() ; )
      if(((ValueChangeMonitor)e.nextElement()).isTriggd())return true;
    return false;
  }
  
  void addMonitor(ValueChangeMonitor m){
    theEvents.addElement(m);
    m.attach(semaphore);
  }

}





